package com.benmei.ntlive.service;

import com.benmei.ntlive.dto.ntmsg.cons.Action;
import com.benmei.ntlive.constant.Constants;
import com.benmei.ntlive.dao.ClassRoomDao;
import com.benmei.ntlive.dao.ClassRoomEntryLogDao;
import com.benmei.ntlive.dao.MemberDao;
import com.benmei.ntlive.dao.TeacherDao;
import com.benmei.ntlive.dto.DrawingResponse;
import com.benmei.ntlive.dto.EraserResponse;
import com.benmei.ntlive.dto.TcpRequest;
import com.benmei.ntlive.dto.ToPageResponse;
import com.benmei.ntlive.entity.*;
import com.benmei.ntlive.exception.NtClientException;
import com.benmei.ntlive.exception.NtServerException;
import com.benmei.ntlive.socket.server.netty.SessionRepository;
import com.benmei.ntlive.utils.JsonUtil;
import com.benmei.ntlive.vo.Room;
import com.benmei.ntlive.vo.Session;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.Map;

/**
 * Created by Peter on 2017/9/7.
 */
@Service
public class LiveService {
    private static Logger logger = LoggerFactory.getLogger(LiveService.class);
    @Autowired
    private TeacherDao teacherDao;

    @Autowired
    private MemberDao memberDao;
    @Autowired
    private ClassRoomDao classRoomDao;

    @Autowired
    private ClassRoomEntryLogDao classRoomEntryLogDao;

    @Autowired
    private SessionRepository sessionRepository;


    public Teacher getTeacherByToken(String token) {
        return teacherDao.getByToken(token);
    }

    public Member getMemberByToken(String token) {
        return memberDao.getByToken(token);
    }

    /**
     * 处理业务逻辑
     *
     * @param ctx
     * @param req
     */
    public void process(ChannelHandlerContext ctx, TcpRequest req, String action) throws NtClientException {
        if (Action.TO_PAGE.getName().equalsIgnoreCase(action)) {
            toPage(ctx, req, action);
        } else if (Action.DRAWING.getName().equalsIgnoreCase(action)) {
            drawing(ctx, req, action);
        } else if (Action.ERASER.getName().equalsIgnoreCase(action)) {
            eraser(ctx, req, action);
        } else {
            throw new NtClientException("Invalid action '" + action+"'");
        }
    }

    // 涂鸦
    public void drawing(final ChannelHandlerContext ctx, TcpRequest req, final String action) {
        try {
            Map<String, Object> body = req.getBody();
            if (body == null) {
                throw new NtClientException("The parameter 'body' is required", action);
            }

            Object obj_roomId = body.get("roomId");
            if (obj_roomId == null) {
                throw new NtClientException("The parameter 'roomId' is required", action);
            }
            Integer roomId = null;
            try {
                roomId = Integer.parseInt(obj_roomId.toString());
            } catch (NumberFormatException e) {
                throw new NtClientException("The parameter 'roomId' must be number, roomId=" + obj_roomId.toString(), action);
            }

            Object trails = body.get("trails");
            if (trails == null) {
                throw new NtClientException("The parameter 'trails' is required", action);
            }

            // 根据roomId获取房间会话
            Room room = sessionRepository.get(roomId);
            if (room == null) {
                throw new NtClientException("Room session do not exists, The roomId=" + roomId, action);
            }

            final ClassRoom classRoom = classRoomDao.findById(roomId);
            if (classRoom == null) {
                throw new NtClientException("ClassRoom do not exists, The roomId=" + roomId, action);
            }
            final Session student = room.getStudent();

            final DrawingResponse drawingResponse = new DrawingResponse(action, trails);
            if (student == null) {
                throw new NtClientException("Student has bean offline.", action);
            } else {
                student.getChannel().writeAndFlush(JsonUtil.toJson(drawingResponse) + Constants.delimiter).addListener(new ChannelFutureListener() {
                    @Override
                    public void operationComplete(ChannelFuture future) throws Exception {
                        if (future.isSuccess()) {
                            logger.info("涂鸦发送成功 to: " +student.getChannel().remoteAddress());
//                            ctx.channel().writeAndFlush(JsonUtil.toJson(response) + Constants.delimiter);
                        } else {
                            logger.error("涂鸦发送失败 to: "+student.getChannel().remoteAddress()+"原因为:", future.cause());
//                            ctx.channel().writeAndFlush(new NtClientException("TO_PAGE is error:" + future.cause().getMessage(), action).toJson());
                        }
                    }
                });
            }


        } catch (NtClientException e) {
            ctx.channel().writeAndFlush(e.toJson() + Constants.delimiter);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            ctx.channel().writeAndFlush(new NtServerException("The parameter 'page' is required", action).toJson() + Constants.delimiter);
        }

        logger.info("Drawing :: from" + ctx.channel().remoteAddress().toString() + "---->");
    }

    // 橡皮檫
    public void eraser(final ChannelHandlerContext ctx, TcpRequest req, final String action) {
        try {
            Object obj_roomId = req.getBody().get("roomId");
            if (obj_roomId == null) {
                throw new NtClientException("The parameter 'roomId' is required", action);
            }
            Integer roomId = null;
            try {
                roomId = Integer.parseInt(obj_roomId.toString());
            } catch (NumberFormatException e) {
                throw new NtClientException("The parameter 'roomId' must be number, the roomId=" + obj_roomId.toString(), action);
            }

            // 根据roomId获取房间会话
            Room room = sessionRepository.get(roomId);
            if (room == null) {
                throw new NtClientException("Room session do not exists, the roomId=" + roomId, action);
            }

            final ClassRoom classRoom = classRoomDao.findById(roomId);
            if (classRoom == null) {
                throw new NtClientException("ClassRoom do not exists, the roomId=" + roomId, action);
            }

            final EraserResponse response = new EraserResponse(action);
            final Session student = room.getStudent();
            if (student == null) {
                throw new NtClientException("Student has bean offline.", action);
            } else {
                student.getChannel().writeAndFlush(JsonUtil.toJson(response) + Constants.delimiter).addListener(new ChannelFutureListener() {
                    @Override
                    public void operationComplete(ChannelFuture future) throws Exception {
                        if (future.isSuccess()) {
                            logger.info("橡皮檫发送成功 to:" + student.getChannel().remoteAddress());
                            ctx.channel().writeAndFlush(JsonUtil.toJson(response) + Constants.delimiter);
                        } else {
                            logger.error("橡皮檫发送失败 to:" + student.getChannel().remoteAddress()+", 原因为:", future.cause());
                            ctx.channel().writeAndFlush(new NtClientException("Eraser is error:" + future.cause().getMessage(), action).toJson());
                        }
                    }
                });
            }


        } catch (NtClientException e) {
            ctx.channel().writeAndFlush(e.toJson() + Constants.delimiter);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            ctx.channel().writeAndFlush(new NtServerException("系统错误", action).toJson() + Constants.delimiter);
        }

        logger.info("Eraser :: " + ctx.channel().remoteAddress().toString() + "---->" + JsonUtil.toJson(req));
    }

    // 翻页
    public void toPage(final ChannelHandlerContext ctx, TcpRequest req, final String action) {
        try {
            Object obj_roomId = req.getBody().get("roomId");
            if (obj_roomId == null) {
                throw new NtClientException("The parameter 'roomId' is required", action);
            }
            Integer roomId = null;
            try {
                roomId = Integer.parseInt(obj_roomId.toString());
            } catch (NumberFormatException e) {
                throw new NtClientException("The parameter 'roomId' must be number, roomId=" + obj_roomId.toString(), action);
            }


            Object obj_page = req.getBody().get("page");
            if (obj_page == null) {
                throw new NtClientException("The parameter 'page' is required", action);
            }
            final Integer page;
            try {
                page = Integer.parseInt(obj_page.toString());
            } catch (NumberFormatException e) {
                throw new NtClientException("The parameter 'page' must be number, page=" + obj_page.toString(), action);
            }

            // 根据roomId获取房间会话
            Room room = sessionRepository.get(roomId);
            if (room == null) {
                throw new NtClientException("Room session do not exists, The roomId=" + roomId, action);
            }


            final ClassRoom classRoom = classRoomDao.findById(roomId);
            if (classRoom == null) {
                throw new NtClientException("ClassRoom do not exists, The roomId=" + roomId, action);
            }
//            Integer studyPage = memberDao.findStudyPage(classRoom.getMemb_id(), classRoom.getCou_id());
//            studyPage = studyPage == null ? 0 : studyPage;

            final ToPageResponse response = new ToPageResponse(action, page);
            final Session student = room.getStudent();
            if (student == null) {
                throw new NtClientException("翻页发送失败 Student has bean offline.", action);
            } else {
                student.getChannel().writeAndFlush(JsonUtil.toJson(response) + Constants.delimiter).addListener(new ChannelFutureListener() {
                    @Override
                    public void operationComplete(ChannelFuture future) throws Exception {
                        if (future.isSuccess()) {
                            logger.info("翻页发送成功 to: "+ student.getChannel().remoteAddress());
                            ctx.channel().writeAndFlush(JsonUtil.toJson(response) + Constants.delimiter);
                            Integer lastPageNum = memberDao.findStudyPage(classRoom.getMemb_id(),classRoom.getCou_id());
                            if(lastPageNum==null){
                                MemberCourse memberCourse = new MemberCourse();
                                memberCourse.setCou_id(classRoom.getCou_id());
                                memberCourse.setMemb_id(classRoom.getMemb_id());
                                Date now = new Date();
                                memberCourse.setEnd_time(now);
                                memberCourse.setStart_time(now);
                                memberCourse.setStudy_page(page);
                                memberDao.insertStudyPage(memberCourse);
                            }else{
                                memberDao.updateStudyPage(classRoom.getMemb_id(), classRoom.getCou_id(), page);
                            }
                        } else {
                            logger.error("翻页发送失败 to: "+ student.getChannel().remoteAddress()+ ", 原因为:", future.cause());
                            ctx.channel().writeAndFlush(new NtClientException("TO_PAGE is error:" + future.cause().getMessage(), action).toJson() + Constants.delimiter);
                        }
                    }
                });
            }


        } catch (NtClientException e) {
            ctx.channel().writeAndFlush(e.toJson() + Constants.delimiter);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            ctx.channel().writeAndFlush(new NtServerException("The parameter 'page' is required", action).toJson() + Constants.delimiter);
        }

        logger.info("TO_PAGE :: " + ctx.channel().remoteAddress().toString() + "---->" + JsonUtil.toJson(req));
    }

    public void roomLog(ClassRoomEntryLog roomLog) {
        classRoomEntryLogDao.insertSelective(roomLog);
    }

    public ClassRoom findRoomById(Integer roomId) {
        return classRoomDao.findById(roomId);
    }
}
